/*
 * @Author: fisher
 * @Date: 2024-03-19 17:24:12
 * @LastEditors: fisher luthor-li@qq.com
 * @LastEditTime: 2024-08-26 16:48:28
 * @FilePath: \pscluster\services\clusterService.js
 * @Description:
 */
const clusterJson = require('../cluster.json')
const fs = require('fs-extra')
const path = require('path')
const dayjs = require('dayjs')
const { execSync } = require('child_process')
const { id } = clusterJson
const { getSysInfo, getProcess } = require('../utils/sysInfo')
const { post } = require('../utils/request')
const { syncFile } = require('../utils/uefile.js')
let _id = ''
if (id) {
  _id = id
}
let heartTimer = null
const heartbeat = async () => {
  // console.log('开启 heartbeat')
  const sysinfo = await getSysInfo()
  const data = {
    id: _id,
    performance: {
      gpuTotal: sysinfo.gpu.total,
      gpuUsage: sysinfo.gpu.used,
      memoryTotal: sysinfo.memory.total,
      memoryUsage: sysinfo.memory.used
    }
  }
  await post('/cluster/updateCluster', data)
  // console.log('syncFileStatus==', syncFileStatus)
}
const registerCluster = async () => {
  if (_id) {
    // 存在_id直接开启心跳发送，激活集群节点
    console.log('存在_id直接开启心跳发送，激活集群节点')
    startHeartbeat()
  } else {
    // 不存在_id，重新注册
    console.log('不存在_id注册集群节点')
    const sysinfo = await getSysInfo()
    const data = {
      host: process.env.HOST,
      port: process.env.PORT,
      protocol: process.env.PROTOCOL,
      performance: {
        gpuTotal: sysinfo.gpu.total,
        gpuUsage: sysinfo.gpu.used,
        memoryTotal: sysinfo.memory.total,
        memoryUsage: sysinfo.memory.used
      }
    }
    post('/cluster/registerCluster', data).then(async res => {
      // 存储当前集群节点id
      if (res.status) {
        _id = res.data._id
        // 指定配置文件路径
        const clusterPath = path.resolve(__dirname, '../cluster.json') // 根据您的实际配置文件位置来更改路径
        // 读取 JSON 配置文件内容
        const clusterJson = await fs.readJson(clusterPath)
        // 修改配置文件
        clusterJson.id = _id
        // 写回 JSON 配置文件
        await fs.writeJson(clusterPath, clusterJson, { spaces: 2 })
        // 开启心跳发送
        startHeartbeat()
        // 同步文件
        syncFile(res.data._id)
      }

      // const url = '/uefile/syncFile/yantian2.zip'
      // const destPath = path.resolve(__dirname, '../bigfileUploads/yantian2.zip')
      // downloadFile(url, destPath, (downloadedLength, totalLength) => {
      //   const percentage = (downloadedLength / totalLength) * 100
      //   console.log(`Downloaded: ${percentage.toFixed(2)}%`)
      // }).then(res => {
      //   console.log('downloadFile finish', res)
      // })
    })
  }
}
/**
 * @description: 停止心跳发送
 * @return {*}
 */
const stopHeartbeat = () => {
  clearInterval(heartTimer)
  heartTimer = null
  // 停止ue工程逻辑
  // 。。。。
}

const deleteCluster = async () => {
  stopHeartbeat()
  // 指定配置文件路径
  const clusterPath = path.resolve(__dirname, '../cluster.json') // 根据您的实际配置文件位置来更改路径
  // 读取 JSON 配置文件内容
  const clusterJson = await fs.readJson(clusterPath)
  // 修改配置文件
  clusterJson.id = ''
  // 写回 JSON 配置文件
  await fs.writeJson(clusterPath, clusterJson, { spaces: 2 })
  // 执行停止当前koa服务的操作
  execSync('pm2 delete all')
}

/**
 * @description: 重启心跳
 * @return {*}
 */
const startHeartbeat = () => {
  // 存在集群节点id则直接启动心跳
  if (_id) {
    heartbeat()
    heartTimer = setInterval(heartbeat, 30000)
  } else {
    // 不存在节点id，重新注册
    registerCluster()
  }
}

const clustersyncFile = async clusterId => {
  try {
    await syncFile(clusterId)
  } catch (err) {
    throw new HttpError(err.message, 400)
  }
}

const getprocess = async () => {
  try {
    // 指定配置文件路径
    const clusterPath = path.resolve(__dirname, '../cluster.json') // 根据您的实际配置文件位置来更改路径
    // 读取 JSON 配置文件内容
    const clusterJson = await fs.readJson(clusterPath)
    const listCmd = `pm2 jlist`
    const status = execSync(listCmd)
    const essentialInfo = JSON.parse(status).map(process => {
      console.log('process.pm2_env', process.pm2_env)
      return {
        clusterId: clusterJson.id,
        pid: process.pid,
        name: process.name,
        status: process.pm2_env.status,
        restartTime: process.pm2_env.restart_time,
        memory: process.monit.memory,
        cpu: process.monit.cpu,
        createAt: dayjs(parseInt(process.pm2_env.created_at)).format(
          'YYYY-MM-DD HH:mm:ss'
        )
      }
    })
    for (let i = 0, len = essentialInfo.length; i < len; i++) {
      if (essentialInfo[i].name.startsWith('ue_')) {
        const res = await getProcess(essentialInfo[i].pid)
        essentialInfo[i].cpu = res.cpu
        essentialInfo[i].memory = res.memory
      }
    }
    return essentialInfo
  } catch (err) {
    throw new HttpError(err.message, 400)
  }
}

const reloadProcess = async process => {
  try {
    const listCmd = `pm2 restart ${process}`
    execSync(listCmd)
  } catch (err) {
    throw new HttpError(err.message, 400)
  }
}
module.exports = {
  startHeartbeat,
  stopHeartbeat,
  registerCluster,
  deleteCluster,
  clustersyncFile,
  getprocess,
  reloadProcess
}
